package com.sale.goods.service.impl;

import cn.hutool.core.util.ObjectUtil;
import com.baomidou.mybatisplus.core.conditions.Wrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.IdWorker;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.sale.common.core.constant.CacheNames;
import com.sale.common.core.exception.GlobalException;
import com.sale.common.core.utils.StringUtils;
import com.sale.common.mybatis.core.page.PageQuery;
import com.sale.common.mybatis.core.page.TableDataInfo;
import com.sale.common.redis.utils.CacheUtils;
import com.sale.common.satoken.utils.LoginHelper;
import com.sale.goods.domain.GoodsInvoicePin;
import com.sale.goods.domain.GoodsMaterial;
import com.sale.goods.domain.dto.GoodsInvoicePinDto;
import com.sale.goods.domain.dto.GoodsMaterialDto;
import com.sale.goods.domain.dto.single.GoodsInvoicePinSingle;
import com.sale.goods.domain.vo.GoodsInvoicePinVo;
import com.sale.goods.mapper.GoodsInvoicePinMapper;
import com.sale.goods.mapper.GoodsMaterialMapper;
import com.sale.goods.service.IGoodsInvoicePinService;
import com.sale.order.api.RemoteCustomerService;
import com.sale.storage.api.RemotePurchaseReceiptService;
import com.sale.storage.api.vo.QuantityDataVo;
import com.sale.storage.api.vo.UpdateInvoicedQuantityVo;
import com.sale.system.api.RemoteMaterialService;
import com.sale.system.api.RemoteReviewService;
import com.sale.system.api.RemoteSubsidiary;
import com.sale.system.api.domain.SysDictData;
import com.sale.system.api.domain.SysMaterial;
import com.sale.system.api.domain.vo.SysAuditHistoryVo;
import lombok.RequiredArgsConstructor;
import org.apache.dubbo.config.annotation.DubboReference;
import org.springframework.beans.BeanUtils;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.math.BigDecimal;
import java.util.*;
import java.util.stream.Collectors;

/**
 * @Description 销项税发票实现类
 * @Date 23-07-19
 * @Author hl
 **/
@RequiredArgsConstructor
@Service
public class GoodsInvoicePinServiceImpl implements IGoodsInvoicePinService {

    private final GoodsInvoicePinMapper goodSInvoicePinMapper;

    private final GoodsMaterialMapper goodsMaterialMapper;

    @DubboReference
    private final RemoteReviewService remoteReviewService;

    @DubboReference
    private final RemoteMaterialService remoteMaterialService;

    @DubboReference
    private final RemoteSubsidiary remoteSubsidiary;

    @DubboReference
    private final RemoteCustomerService remoteCustomerService;

    @DubboReference
    private final RemotePurchaseReceiptService remotePurchaseReceiptService;


    /**
     * 分页查询销项税发票
     *
     * @param goodSInvoicePinVo 销项税发票,pageQuery 分页参数
     * @return TableDataInfo<GoodSInvoicePinDto>
     */
    @Override
    public TableDataInfo<GoodsInvoicePinDto> selectInvoicePinList(GoodsInvoicePinVo goodSInvoicePinVo, PageQuery pageQuery) {
        Page<GoodsInvoicePinDto> page = goodSInvoicePinMapper.selectInvoicePinList(pageQuery.build(), this.buildQueryWrapper(goodSInvoicePinVo));
        //渲染字典
        List<GoodsInvoicePinDto> list= page.getRecords();
        List<SysDictData> netArray = CacheUtils.get(CacheNames.SYS_DICT, "goods_invoice_type");
        Map<String, String> netMap = netArray.stream().collect(Collectors.toMap(SysDictData::getDictValue, SysDictData::getDictLabel));
        List<SysDictData> netArray3 = CacheUtils.get(CacheNames.SYS_DICT, "bill_state");
        Map<String, String> netMap3 = netArray3.stream().collect(Collectors.toMap(SysDictData::getDictValue, SysDictData::getDictLabel));
        //客户
        Map<String, String> map1= remoteCustomerService.getOpenCustomerFinance();
        //收支类别
        Map<String, String> map2 = remoteSubsidiary.selectIncomeList();
        for (GoodsInvoicePinDto dto:
        list) {
            //发票种类
            dto.setInvoiceSpeciesDict(netMap.get(dto.getInvoiceSpecies()));
            //收支类别
            dto.setInvoiceTypeDict(map2.get(dto.getInvoiceType()));
            //状态
            dto.setInvoiceStatusDict(netMap3.get(dto.getInvoiceStatus()));
            //客户
            dto.setClientName(map1.get(dto.getClientName()));
        }
        return TableDataInfo.build(page);
    }

    private Wrapper<GoodsInvoicePinVo> buildQueryWrapper(GoodsInvoicePinVo goodSInvoicePinVo) {
        QueryWrapper<GoodsInvoicePinVo> wrapper = Wrappers.query();
        String client = goodSInvoicePinVo.getClientName();
        if(StringUtils.isNotBlank(client)){
            goodSInvoicePinVo.setClientName(remoteCustomerService.getCodeByCustomerName(client));
        }
        wrapper
            .like(ObjectUtil.isNotNull(goodSInvoicePinVo.getInvoiceNumber()), "t1.invoice_number", goodSInvoicePinVo.getInvoiceNumber())
            .like(StringUtils.isNotBlank(goodSInvoicePinVo.getInvoiceCode()), "t1.invoice_code", goodSInvoicePinVo.getInvoiceCode())
            .like(StringUtils.isNotBlank(goodSInvoicePinVo.getInvoiceSpecies()), "t1.invoice_species", goodSInvoicePinVo.getInvoiceSpecies())
            .like(StringUtils.isNotBlank(goodSInvoicePinVo.getInvoiceType()), "t1.invoice_type", goodSInvoicePinVo.getInvoiceType())
            .eq(StringUtils.isNotBlank(goodSInvoicePinVo.getClientName()), "t1.client_name", goodSInvoicePinVo.getClientName())
            .eq(StringUtils.isNotBlank(goodSInvoicePinVo.getInvoiceStatus()), "t1.invoice_status", goodSInvoicePinVo.getInvoiceStatus()).between(goodSInvoicePinVo.getBeginTime() != null && goodSInvoicePinVo.getEndTime() != null,
                "t1.invoice_time", goodSInvoicePinVo.getBeginTime(), goodSInvoicePinVo.getEndTime());
        return wrapper;
    }

    /**
     * 新增销项税发票
     *
     * @param goodSInvoicePinVo
     * @return int
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public int insertInvoicePin(GoodsInvoicePinVo goodSInvoicePinVo) throws Exception {
        String number = goodSInvoicePinVo.getInvoiceNumber();
        int count = goodSInvoicePinMapper.selectNumberCount(number);
        if(count>0){
            throw new GlobalException("该发票号码已存在!");
        }
        GoodsInvoicePin pin = new GoodsInvoicePin();
        BeanUtils.copyProperties(goodSInvoicePinVo, pin);
        pin.setInvoiceStatus(1);
        List<GoodsMaterial> list = goodSInvoicePinVo.getMaterialRawList();
        Long pinId = IdWorker.getId();
        //合计金额
        BigDecimal b1 = new BigDecimal(0);
        //合计税额
        BigDecimal b2 = new BigDecimal(0);
        //新增物料明细
        for (GoodsMaterial goods :
            list) {
            goods.setGoodsId(IdWorker.getId());
            goods.setInvoiceId(pinId);
            b1 = b1.add(goods.getGoodsAmount());
            b2 = b2.add(goods.getGoodsTaxAmount());
        }
        //价税合计
        BigDecimal b3 = b1.add(b2);
        pin.setTaxExclusive(b1);
        pin.setTheExclusive(b2);
        pin.setPriceTax(b3);
        pin.setInvoicePinId(pinId);
        int os = goodSInvoicePinMapper.insert(pin);
        goodsMaterialMapper.insertBatch(list);
        return os;
    }

    /**
     * 查询销项税发票
     *
     * @param invoicePinId
     * @return GoodSInvoicePinDto
     */
    @Override
    public GoodsInvoicePinSingle selectInvoicePinById(long invoicePinId) {
        GoodsInvoicePin pin = goodSInvoicePinMapper.selectById(invoicePinId);
        GoodsInvoicePinSingle single = new GoodsInvoicePinSingle();
        BeanUtils.copyProperties(pin, single);
        //字典
        List<SysDictData> netArray = CacheUtils.get(CacheNames.SYS_DICT, "goods_invoice_type");
        Map<String, String> netMap = netArray.stream().collect(Collectors.toMap(SysDictData::getDictValue, SysDictData::getDictLabel));
        //发票种类
        single.setInvoiceSpeciesDict(netMap.get(single.getInvoiceSpecies()));
        //发票明细
        List<GoodsMaterialDto> goodsList = goodsMaterialMapper.selectByMaterial(invoicePinId);
        for (GoodsMaterialDto goods : goodsList) {
            SysMaterial sys = remoteMaterialService.selectMaterial(goods.getMaterialId());
            BeanUtils.copyProperties(sys, goods);
        }
        single.setMaterialRawList(goodsList);
        return single;
    }

    /**
     * 删除销项税发票
     *
     * @param invoicePinId
     * @return int
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public int deleteInvoicePinById(Long invoicePinId) {
        int os = goodSInvoicePinMapper.deleteById(invoicePinId);
        Map<String, Object> map = new HashMap<>();
        map.put("invoice_id", invoicePinId);
        List<GoodsMaterial> goodsList = goodsMaterialMapper.selectByMap(map);
        if (goodsList.size() > 0) {
            os = goodsMaterialMapper.deleteByMap(map);
        }
        return os;
    }

    /**
     * 修改销项税发票
     *
     * @param goodSInvoicePinVo
     * @return int
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public int updateInvoicePinEdit(GoodsInvoicePinVo goodSInvoicePinVo) {
        if(goodSInvoicePinVo.getInvoiceStatus().equals("4")){
            SysAuditHistoryVo vo = new SysAuditHistoryVo();
            vo.setPerms("goods:invoicePin:review");
            vo.setAuditDoc(goodSInvoicePinVo.getInvoiceCode());
            int is = remoteReviewService.editHistory(vo);
            if (is == 0) {
                throw new GlobalException("修改失败,未找到审核历史!");
            }
        }
        GoodsInvoicePin pin = new GoodsInvoicePin();
        BeanUtils.copyProperties(goodSInvoicePinVo, pin);
        List<GoodsMaterial> list = goodSInvoicePinVo.getMaterialRawList();
        Long pinId = pin.getInvoicePinId();
        Map<String, Object> map = new HashMap<>();
        map.put("invoice_id", pinId);
        goodsMaterialMapper.deleteByMap(map);
        //合计金额
        BigDecimal b1 = new BigDecimal(0);
        //合计税额
        BigDecimal b2 = new BigDecimal(0);
        //新增物料明细
        for (GoodsMaterial goods :
            list) {
            goods.setGoodsId(IdWorker.getId());
            goods.setInvoiceId(pinId);
            b1 = b1.add(goods.getGoodsAmount());
            b2 = b2.add(goods.getGoodsTaxAmount());
        }
        //价税合计
        BigDecimal b3 = b1.add(b2);
        pin.setTaxExclusive(b1);
        pin.setTheExclusive(b2);
        pin.setPriceTax(b3);
        pin.setInvoicePinId(pinId);
        pin.setInvoiceStatus(1);
        int os = goodSInvoicePinMapper.updateById(pin);
        goodsMaterialMapper.insertBatch(list);
        return os;
    }

    /**
     * 提交销项税发票
     *
     * @param invoicePinId
     * @return int
     */
    @Override
    public int submitReview(Long invoicePinId) {
        GoodsInvoicePin Pin = goodSInvoicePinMapper.selectById(invoicePinId);
        int status = Pin.getInvoiceStatus();
        if (status != 1) {
            throw new GlobalException("只有待提交状态才能提交审核");
        }
        GoodsInvoicePin goods = new GoodsInvoicePin();
        goods.setInvoicePinId(invoicePinId);
        goods.setInvoiceStatus(2);
        return goodSInvoicePinMapper.updateById(goods);
    }

    /**
     * 撤销销项税发票
     *
     * @param invoicePinId
     * @return int
     */
    @Override
    public int deleteReview(Long invoicePinId) {
        GoodsInvoicePin goods = goodSInvoicePinMapper.selectById(invoicePinId);
        int status = goods.getInvoiceStatus();
        if (status != 2) {
            throw new GlobalException("只有待审核状态才能撤销审核");
        }
        GoodsInvoicePin Pin = new GoodsInvoicePin();
        Pin.setInvoicePinId(invoicePinId);
        Pin.setInvoiceStatus(1);
        return goodSInvoicePinMapper.updateById(Pin);
    }

    /**
     * 审核销项税发票
     *
     * @param goodSInvoicePinVo
     * @return int
     */
    @Override
    public int goodSExamineReview(GoodsInvoicePinVo goodSInvoicePinVo) throws Exception {
        SysAuditHistoryVo sysAuditHistoryVo = new SysAuditHistoryVo();
        Long id = goodSInvoicePinVo.getInvoicePinId();
        GoodsInvoicePin pin = goodSInvoicePinMapper.selectById(id);
        String perms = "goods:invoicePin:review";
        sysAuditHistoryVo.setPerms(perms);
        sysAuditHistoryVo.setModuleType(3);
        sysAuditHistoryVo.setAuditState(goodSInvoicePinVo.getAuditState());
        sysAuditHistoryVo.setAuditRemarks(goodSInvoicePinVo.getAuditOpinion());
        sysAuditHistoryVo.setAuditDoc(pin.getInvoiceCode());
        sysAuditHistoryVo.setUserId(LoginHelper.getUserId());
        int data = remoteReviewService.getSequence(sysAuditHistoryVo);
        if (data == 0) {
            throw new GlobalException("未对该审核销行配置");
        }
        //1:通过，2：审核中，3：没权限 4:该人已经审核过
        GoodsInvoicePin goods = new GoodsInvoicePin();
        goods.setInvoicePinId(id);
        switch (data) {
            case 1:
                if(goodSInvoicePinVo.getAuditState()==2){
                    goods.setInvoiceStatus(4);
                }else{
                    goods.setInvoiceStatus(5);
                    UpdateInvoicedQuantityVo vo1 = new UpdateInvoicedQuantityVo();
                    List<QuantityDataVo> list2 = new ArrayList<>();
                    Map<String, Object> map = new HashMap<>();
                    map.put("invoice_id", id);
                    List<GoodsMaterial> list1 = goodsMaterialMapper.selectByMap(map);
                    list1.stream().map(x1 -> {
                        QuantityDataVo v1 = new QuantityDataVo();
                        v1.setReceiptNumber(x1.getReceiptNo());
                        v1.setQuantity(String.valueOf(x1.getGoodsNum()));
                        v1.setApprovedAmount(x1.getGoodsAmount());
                        v1.setDocumentType("销售发货");
                        return v1;
                    }).forEach(list2::add);
                    vo1.setList(list2);
                    remotePurchaseReceiptService.updateInvoicedQuantity(vo1);
                }
                break;
            case 2:
                goods.setInvoiceStatus(3);
                break;
            case 3:
                if (data == 0) {
                    throw new GlobalException("不具备审核权限");
                }
                break;
            case 4:
                if (data == 0) {
                    throw new GlobalException("请勿重复审核");
                }
                break;
        }
        //审核人
        goods.setExamineBy(LoginHelper.getUsername());
        //审核日期
        goods.setExamineTime(new Date());
        return goodSInvoicePinMapper.updateById(goods);
    }

    /**
     * 认证
     *
     * @param invoicePinId
     * @return int
     */
    @Override
    public int goodsThe(Long invoicePinId) {
        GoodsInvoicePin Pin = goodSInvoicePinMapper.selectById(invoicePinId);
        int status = Pin.getInvoiceStatus();
        if (status != 5) {
            throw new GlobalException("只有待认证状态才能销行认证");
        }
        GoodsInvoicePin goods = new GoodsInvoicePin();
        goods.setInvoicePinId(invoicePinId);
        goods.setInvoiceStatus(6);
        return goodSInvoicePinMapper.updateById(goods);
    }


}
